// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

#ifndef CANGJIE_MIGRATOR_ACTIONS_ACTION
#define CANGJIE_MIGRATOR_ACTIONS_ACTION

#include "Actions/KindType.h"
#include "Actions/Replace.h"
#include "Actions/Comment.h"

#include <variant>

namespace CangjieMigrator::Actions {

using Action = std::variant<Replace, Comment>;

KindType GetKind(const Action &action);

std::string ToString(const Action &action);

// Helper: Overload pattern for std::visit
template <typename... Fs>
struct Overload : Fs... {
    using Fs::operator()...;
    explicit constexpr Overload(Fs&&... fs) : Fs(std::forward<Fs>(fs))... {}
};

// Check if F can be called with const T&
template <typename F, typename T>
using IsValidVisitor = std::is_invocable<F, const T&>;

// Count how many variant alternatives F can handle
template <typename Variant, typename F, std::size_t... Is>
constexpr std::size_t MatchCountImpl(std::index_sequence<Is...>)
{
    return (static_cast<std::size_t>(
        IsValidVisitor<F, std::variant_alternative_t<Is, Variant>>::value) + ...);
}

template <typename Variant, typename F>
constexpr std::size_t MatchCount()
{
    return MatchCountImpl<Variant, F>(
        std::make_index_sequence<std::variant_size_v<Variant>>{});
}

template <typename Variant, typename... Fs>
void Dispatch(const Variant& variant, Fs&&... fns)
{
    constexpr bool eachMatchesOne = ((MatchCount<Variant, Fs>() == 1) && ...);
    constexpr bool countMatches   = (sizeof...(Fs) == std::variant_size_v<Variant>);

    static_assert(eachMatchesOne,
        "Each visitor must handle exactly one variant alternative (with const T&)");
    static_assert(countMatches,
        "Number of visitors must match the number of variant alternatives");

    std::visit(Overload(std::forward<Fs>(fns)...), variant);
}

PositionRange GetRange(const Action &action);

} // CangjieMigrator::Actions

#endif // CANGJIE_MIGRATOR_ACTIONS_ACTION
